use crate::imu::{FRAME_LEN, HEADER};

// 状态机定义
#[derive(Debug, Clone, Copy)]
enum ParseState {
    WaitHeader,  // 等待帧头
    WaitType,  // 等待帧类型
    CollectData,  // 正在收集数据
}

pub struct FrameParser {
    state: ParseState,  // 当前解析状态
    frame: [u8; FRAME_LEN],  // 当前正在构建的数据帧
    idx: usize,  // 当前帧内字节索引位置
}

impl FrameParser {
    /// 实例化一个新的解析器
    pub fn new() -> Self {
        Self {
            state: ParseState::WaitHeader,
            frame: [0; FRAME_LEN],
            idx: 0,
        }
    }

    /// 单字节解析
    /// 按照顺序传入缓冲区的字节
    /// 正在解析过程中，或者没有提取到一个完整帧时返回None
    /// 当成功解析时返回Some(frame)
    pub fn parse_byte(&mut self, byte: u8) -> Option<[u8; FRAME_LEN]> {
        return match self.state {
            ParseState::WaitHeader => {
                if byte == HEADER {
                    self.frame[self.idx] = byte;
                    self.idx += 1;
                    self.state = ParseState::WaitType;
                }
                None
            }
            ParseState::WaitType => {
                self.frame[self.idx] = byte;
                self.idx += 1;
                self.state = ParseState::CollectData;

                None
            }
            ParseState::CollectData => {
                self.frame[self.idx] = byte;
                self.idx += 1;

                if self.idx >= 11 {
                    let result = self.frame;
                    self.reset_state();

                    if verify_sum(&result) {
                        Some(result)
                    }
                    else {
                        println!("parse failed");
                        None  // 校验失败
                    }

                } else {
                    None
                }
            }
        }
    }

    /// 缓冲区解析方法
    /// 对每个成功解析的帧调用回调函数
    pub fn parse_buffer<T: FnMut(&[u8])>(&mut self, buffer: &[u8], mut callback: T) {
        for &byte in buffer {
            if let Some(frame) = self.parse_byte(byte) {
                callback(&frame);
            }
        }
    }

    fn reset_state(&mut self) {
        self.idx = 0;
        self.state = ParseState::WaitHeader;
    }

}

fn verify_sum(frame: &[u8; FRAME_LEN]) -> bool {
    let sum: u8 = frame[..FRAME_LEN - 1]
        .iter()
        .fold(0u8, |acc, &x| {
            acc.wrapping_add(x)
        });

    sum == frame[FRAME_LEN - 1]
}